package com.bawei.module_publish.ui

import android.content.SharedPreferences
import android.view.View
import com.bawei.lib_mvi.base.BaseActivity
import com.bawei.module_publish.databinding.ActivityConfigBinding

class ConfigActivity : BaseActivity() {

    companion object {
        // PLRecordSetting
        const val DEFAULT_MIN_RECORD_DURATION: Long = (3 * 1000).toLong()
        const val DEFAULT_MAX_RECORD_DURATION: Long = (10 * 1000).toLong()
        const val DEFAULT_RECORDING_SPEED_VARIABLE_ENABLED: Boolean = true

        // PLCameraSetting 镜头参数
        const val DEFAULT_PREVIEW_SIZE_RATIO_POS: Int = 0
        const val DEFAULT_PREVIEW_SIZE_LEVEL_POS: Int = 3

        // PLVideoEncodeSetting
        const val DEFAULT_VIDEO_ENCODE_SIZE_LEVEL_POS: Int = 7
        const val DEFAULT_VIDEO_ENCODE_BITRATE_LEVEL_POS: Int = 2
        const val DEFAULT_VIDEO_HARDWARE_ENCODE_ENABLE: Boolean = false

        // PLAudioEncodeSetting
        const val DEFAULT_AUDIO_SAMPLE_RATE: Int = 44100
        const val DEFAULT_AUDIO_CHANNEL_NUM_POS: Int = 0
        const val DEFAULT_AUDIO_ENCODE_BITRATE_LEVEL_POS: Int = 2
        const val DEFAULT_AUDIO_HARDWARE_ENCODE_ENABLE: Boolean = false

        // PLMicrophoneSetting
        const val DEFAULT_SAMPLING_SAMPLE_RATE: Int = 44100
        const val DEFAULT_SAMPLING_FORMAT_POS: Int = 2
        const val DEFAULT_SAMPLING_SOURCE_POS: Int = 1
        const val DEFAULT_SAMPLING_CHANNEL_NUM_POS: Int = 0
        const val DEFAULT_SAMPLING_BLUETOOTH_SCO_ENABLE: Boolean = false
        const val DEFAULT_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE: Boolean = false
        const val DEFAULT_SAMPLING_NSE_ENABLE: Boolean = false
        const val DEFAULT_SAMPLING_AEC_ENABLE: Boolean = false

        // PLWatermarkSetting
        const val DEFAULT_WATERMARK_SETTING_TYPE_POS: Int = 0
        const val DEFAULT_WATERMARK_ALPHA: Int = 255
        const val DEFAULT_WATERMARK_WIDTH: Float = 0f
        const val DEFAULT_WATERMARK_HEIGHT: Float = 0f
        const val DEFAULT_WATERMARK_POSITION_X: Float = 0f
        const val DEFAULT_WATERMARK_POSITION_Y: Float = 0f
        const val DEFAULT_MIRROR_ENCODE_ENABLE: Boolean = false

        // SharedPreferences 保存字段的 key
        const val SP_NAME: String = "Config"

        // PLRecordSetting
        const val KEY_MAX_RECORD_DURATION: String = "MAX_RECORD_DURATION"
        const val KEY_RECORDING_SPEED_VARIABLE_ENABLED: String = "RECORDING_SPEED_VARIABLE_ENABLED"

        // PLShortVideoRecorder
        const val KEY_MIRROR_ENCODE_ENABLE: String = "MIRROR_ENCODE_ENABLE"

        // PLCameraSetting 镜头参数
        const val KEY_PREVIEW_SIZE_RATIO_POS: String = "PREVIEW_SIZE_RATIO_POS"
        const val KEY_PREVIEW_SIZE_LEVEL_POS: String = "PREVIEW_SIZE_LEVEL_POS"

        // PLVideoEncodeSetting
        const val KEY_VIDEO_ENCODE_SIZE_LEVEL_POS: String = "VIDEO_ENCODE_SIZE_LEVEL_POS"
        const val KEY_VIDEO_ENCODE_BITRATE_LEVEL_POS: String = "VIDEO_ENCODE_BITRATE_LEVEL_POS"
        const val KEY_VIDEO_ENCODE_HARDWARE_CODEC_ENABLE: String =
            "VIDEO_ENCODE_HARDWARE_CODEC_ENABLE"

        // PLAudioEncodeSetting
        const val KEY_AUDIO_SAMPLE_RATE: String = "AUDIO_SAMPLE_RATE"
        const val KEY_AUDIO_CHANNEL_NUM_POS: String = "AUDIO_CHANNEL_NUM_POS"
        const val KEY_AUDIO_ENCODE_HARDWARE_CODEC_ENABLE: String =
            "AUDIO_ENCODE_HARDWARE_CODEC_ENABLE"
        const val KEY_AUDIO_ENCODE_BITRATE_LEVEL_POS: String = "AUDIO_ENCODE_BITRATE_LEVEL_POS"

        // PLMicrophoneSetting
        const val KEY_SAMPLING_SAMPLE_RATE: String = "SAMPLING_SAMPLE_RATE"
        const val KEY_SAMPLING_FORMAT_POS: String = "SAMPLING_FORMAT_POS"
        const val KEY_SAMPLING_SOURCE_POS: String = "SAMPLING_SOURCE_POS"
        const val KEY_SAMPLING_CHANNEL_NUM_POS: String = "SAMPLING_CHANNEL_NUM_POS"
        const val KEY_SAMPLING_BLUETOOTH_SCO_ENABLE: String = "SAMPLING_BLUETOOTH_SCO_ENABLE"
        const val KEY_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE: String =
            "SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE"
        const val KEY_SAMPLING_NSE_ENABLE: String = "SAMPLING_NSE_ENABLE"
        const val KEY_SAMPLING_AEC_ENABLE: String = "SAMPLING_AEC_ENABLE"

        // PLWatermarkSetting
        const val KEY_WATERMARK_SETTING_TYPE_POS: String = "WATERMARK_SETTING_TYPE_POS"
        const val KEY_WATERMARK_ALPHA: String = "WATERMARK_ALPHA"
        const val KEY_WATERMARK_WIDTH: String = "WATERMARK_WIDTH"
        const val KEY_WATERMARK_HEIGHT: String = "WATERMARK_HEIGHT"
        const val KEY_WATERMARK_POSITION_X: String = "WATERMARK_POSITION_X"
        const val KEY_WATERMARK_POSITION_Y: String = "WATERMARK_POSITION_Y"
    }

    private val binding: ActivityConfigBinding by lazy {
        ActivityConfigBinding.inflate(layoutInflater)
    }

    override fun getLayoutRootView(): View {
        return binding.root
    }

    private var prefs: SharedPreferences? = null

    override fun initView() {
        prefs = applicationContext.getSharedPreferences(SP_NAME, MODE_PRIVATE)
        setMaxRecordDuration()
        setRecordingSpeedVariableEnabled()
        setMirrorEncode()
        setCameraSetting()
        setVideoEncoding()
        setAudioEncodeSetting()
        setMicrophoneSetting()
        setWatermarkSetting()
    }

    fun onClickBack(view: View?) {
        finish()
    }

    private fun setMaxRecordDuration() {
        val maxRecordDuration: Long =
            prefs!!.getLong(KEY_MAX_RECORD_DURATION, DEFAULT_MAX_RECORD_DURATION)
        binding.maxRecordDurationEdittext.setText(maxRecordDuration.toString())
    }

    private fun setRecordingSpeedVariableEnabled() {
        val speedVariableEnabled: Boolean = prefs!!.getBoolean(
            KEY_RECORDING_SPEED_VARIABLE_ENABLED, DEFAULT_RECORDING_SPEED_VARIABLE_ENABLED
        )
        binding.recordSpeedVariable.isChecked = speedVariableEnabled
    }

    private fun setMirrorEncode() {
        val isMirrorEncode: Boolean =
            prefs!!.getBoolean(KEY_MIRROR_ENCODE_ENABLE, DEFAULT_MIRROR_ENCODE_ENABLE)
        binding.mirrorEncodeSwitch.isChecked = isMirrorEncode
    }

    private fun setCameraSetting() {
        val previewSizeRatioPos: Int =
            prefs!!.getInt(KEY_PREVIEW_SIZE_RATIO_POS, DEFAULT_PREVIEW_SIZE_RATIO_POS)
        val previewSizeLevelPos: Int =
            prefs!!.getInt(KEY_PREVIEW_SIZE_LEVEL_POS, DEFAULT_PREVIEW_SIZE_LEVEL_POS)


        binding.previewSizeRatioSpinner.setSelection(previewSizeRatioPos)
        binding.previewSizeLevelSpinner.setSelection(previewSizeLevelPos)
    }

    private fun setVideoEncoding() {
        val encodingSizeLevelPos: Int =
            prefs!!.getInt(KEY_VIDEO_ENCODE_SIZE_LEVEL_POS, DEFAULT_VIDEO_ENCODE_SIZE_LEVEL_POS)
        val encodingBitrateLevelPos: Int =
            prefs!!.getInt(
                KEY_VIDEO_ENCODE_BITRATE_LEVEL_POS,
                DEFAULT_VIDEO_ENCODE_BITRATE_LEVEL_POS
            )
        val isEncodingHardwareEnable: Boolean = prefs!!.getBoolean(
            KEY_VIDEO_ENCODE_HARDWARE_CODEC_ENABLE,
            DEFAULT_VIDEO_HARDWARE_ENCODE_ENABLE
        )

        binding.encodingSizeLevelSpinner.setSelection(encodingSizeLevelPos)
        binding.encodingBitrateLevelSpinner.setSelection(encodingBitrateLevelPos)
        binding.encodingHardwareCodecSwitch.isChecked = isEncodingHardwareEnable
    }

    private fun setAudioEncodeSetting() {
        val audioSampleRate: Int = prefs!!.getInt(KEY_AUDIO_SAMPLE_RATE, DEFAULT_AUDIO_SAMPLE_RATE)
        val audioChannelNumPos: Int =
            prefs!!.getInt(KEY_AUDIO_CHANNEL_NUM_POS, DEFAULT_AUDIO_CHANNEL_NUM_POS)
        val isAudioEncodeHardwareEnable: Boolean = prefs!!.getBoolean(
            KEY_AUDIO_ENCODE_HARDWARE_CODEC_ENABLE, DEFAULT_AUDIO_HARDWARE_ENCODE_ENABLE
        )
        val audioBitrateLevelPos: Int =
            prefs!!.getInt(
                KEY_AUDIO_ENCODE_BITRATE_LEVEL_POS,
                DEFAULT_AUDIO_ENCODE_BITRATE_LEVEL_POS
            )

        binding.audioSampleRateEdittext.setText(audioSampleRate.toString())
        binding.audioChannelNumSpinner.setSelection(audioChannelNumPos)
        binding.audioEncodeModeLevelSwitch.isChecked = isAudioEncodeHardwareEnable
        binding.audioBitrateLevelSpinner.setSelection(audioBitrateLevelPos)

    }

    private fun setMicrophoneSetting() {
        val samplingSampleRate: Int =
            prefs!!.getInt(KEY_SAMPLING_SAMPLE_RATE, DEFAULT_SAMPLING_SAMPLE_RATE)
        val samplingFormatPos: Int =
            prefs!!.getInt(KEY_SAMPLING_FORMAT_POS, DEFAULT_SAMPLING_FORMAT_POS)
        val samplingSourcePos: Int =
            prefs!!.getInt(KEY_SAMPLING_SOURCE_POS, DEFAULT_SAMPLING_SOURCE_POS)
        val samplingChannelNumPos: Int =
            prefs!!.getInt(KEY_SAMPLING_CHANNEL_NUM_POS, DEFAULT_SAMPLING_CHANNEL_NUM_POS)
        val isSamplingBluetoothSCOEnable: Boolean = prefs!!.getBoolean(
            KEY_SAMPLING_BLUETOOTH_SCO_ENABLE,
            DEFAULT_SAMPLING_BLUETOOTH_SCO_ENABLE
        )
        val isSamplingAudioPTSOptimizeEnable: Boolean = prefs!!.getBoolean(
            KEY_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE, DEFAULT_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE
        )
        val isSamplingNSEEnable: Boolean =
            prefs!!.getBoolean(KEY_SAMPLING_NSE_ENABLE, DEFAULT_SAMPLING_NSE_ENABLE)
        val isSamplingAECEnable: Boolean =
            prefs!!.getBoolean(KEY_SAMPLING_AEC_ENABLE, DEFAULT_SAMPLING_AEC_ENABLE)

        binding.samplingSampleRateEdittext.setText(samplingSampleRate.toString())
        binding.samplingFormatSpinner.setSelection(samplingFormatPos)
        binding.samplingSourceSpinner.setSelection(samplingSourcePos)
        binding.samplingChannelNumSpinner.setSelection(samplingChannelNumPos)
        binding.samplingBluetoothScoSwitch.isChecked = isSamplingBluetoothSCOEnable
        binding.samplingAudioPtsOptimizeSwitch.isChecked = isSamplingAudioPTSOptimizeEnable
        binding.samplingNseSwitch.isChecked = isSamplingNSEEnable
        binding.samplingAecSwitch.isChecked = isSamplingAECEnable
    }

    private fun setWatermarkSetting() {
        val watermarkPositionX: Float =
            prefs!!.getFloat(KEY_WATERMARK_POSITION_X, DEFAULT_WATERMARK_POSITION_X)
        val watermarkPositionY: Float =
            prefs!!.getFloat(KEY_WATERMARK_POSITION_Y, DEFAULT_WATERMARK_POSITION_Y)
        val watermarkAlpha: Int = prefs!!.getInt(KEY_WATERMARK_ALPHA, DEFAULT_WATERMARK_ALPHA)
        val watermarkWidth: Float = prefs!!.getFloat(KEY_WATERMARK_WIDTH, DEFAULT_WATERMARK_WIDTH)
        val watermarkHeight: Float =
            prefs!!.getFloat(KEY_WATERMARK_HEIGHT, DEFAULT_WATERMARK_HEIGHT)
        val watermarkSettingTypePos: Int =
            prefs!!.getInt(KEY_WATERMARK_SETTING_TYPE_POS, DEFAULT_WATERMARK_SETTING_TYPE_POS)

        binding.watermarkPositionXEdittext.setText(watermarkPositionX.toString())
        binding.watermarkPositionYEdittext.setText(watermarkPositionY.toString())
        binding.watermarkAlphaSeekBar.progress = transWatermarkAlphaToProgress(watermarkAlpha)
        binding.watermarkWidthSeekbar.progress = transWatermarkSizeToProgress(watermarkWidth)
        binding.watermarkHeightSeekbar.progress = transWatermarkSizeToProgress(watermarkHeight)
        binding.watermarkSpinner.setSelection(watermarkSettingTypePos)
    }

    private fun transWatermarkAlphaToProgress(watermarkAlpha: Int): Int {
        return (100.0 * (1 - (watermarkAlpha * 1.0 / 255))).toInt()
    }

    private fun transWatermarkSizeToProgress(size: Float): Int {
        return (size * 100f).toInt()
    }

    private fun transProgressToWatermarkAlpha(progress: Int): Int {
        return ((1.0 - progress.toFloat() / 100) * 255).toInt()
    }

    private fun transProgressToWatermarkSize(progress: Int): Float {
        return progress.toFloat() / 100
    }

    override fun onDestroy() {
        saveSharedPreferences()
        super.onDestroy()
    }

    private fun saveSharedPreferences() {
        val prefsEditor: SharedPreferences.Editor = prefs!!.edit()
        // PLRecordSetting
        var maxRecordDuration: Long =
            binding.maxRecordDurationEdittext.getText().toString().toLong()
        if (maxRecordDuration < DEFAULT_MIN_RECORD_DURATION) {
            maxRecordDuration = DEFAULT_MAX_RECORD_DURATION
        }
        prefsEditor.putLong(KEY_MAX_RECORD_DURATION, maxRecordDuration)
        prefsEditor.putBoolean(
            KEY_RECORDING_SPEED_VARIABLE_ENABLED, binding.recordSpeedVariable.isChecked
        )

        // PLShortVideoRecorder
        prefsEditor.putBoolean(KEY_MIRROR_ENCODE_ENABLE, binding.mirrorEncodeSwitch.isChecked)

        // PLCameraSetting 镜头参数
        prefsEditor.putInt(
            KEY_PREVIEW_SIZE_RATIO_POS,
            binding.previewSizeRatioSpinner.selectedItemPosition
        )
        prefsEditor.putInt(
            KEY_PREVIEW_SIZE_LEVEL_POS,
            binding.previewSizeLevelSpinner.selectedItemPosition
        )

        // PLVideoEncodeSetting 视频编码参数
        prefsEditor.putInt(
            KEY_VIDEO_ENCODE_SIZE_LEVEL_POS,
            binding.encodingSizeLevelSpinner.selectedItemPosition
        )
        prefsEditor.putInt(
            KEY_VIDEO_ENCODE_BITRATE_LEVEL_POS,
            binding.encodingBitrateLevelSpinner.selectedItemPosition
        )
        prefsEditor.putBoolean(
            KEY_VIDEO_ENCODE_HARDWARE_CODEC_ENABLE,
            binding.encodingHardwareCodecSwitch.isChecked
        )

        // PLAudioEncodeSetting
        val audioSampleRate = if (binding.audioSampleRateEdittext.text.toString().isNotEmpty()
        ) binding.audioSampleRateEdittext.text.toString().toInt() else 44100
        prefsEditor.putInt(KEY_AUDIO_SAMPLE_RATE, audioSampleRate)
        prefsEditor.putInt(
            KEY_AUDIO_CHANNEL_NUM_POS, binding.audioChannelNumSpinner.selectedItemPosition
        )
        prefsEditor.putBoolean(
            KEY_AUDIO_ENCODE_HARDWARE_CODEC_ENABLE, binding.audioEncodeModeLevelSwitch.isChecked
        )
        prefsEditor.putInt(
            KEY_AUDIO_ENCODE_BITRATE_LEVEL_POS,
            binding.audioBitrateLevelSpinner.selectedItemPosition
        )

        // PLMicrophoneSetting
        val samplingSampleRate = if (binding.samplingSampleRateEdittext.text.toString().isNotEmpty()
        ) binding.samplingSampleRateEdittext.text.toString().toInt() else 44100
        prefsEditor.putInt(KEY_SAMPLING_SAMPLE_RATE, samplingSampleRate)
        prefsEditor.putInt(
            KEY_SAMPLING_FORMAT_POS,
            binding.samplingFormatSpinner.selectedItemPosition
        )
        prefsEditor.putInt(
            KEY_SAMPLING_SOURCE_POS,
            binding.samplingSourceSpinner.selectedItemPosition
        )
        prefsEditor.putInt(
            KEY_SAMPLING_CHANNEL_NUM_POS,
            binding.samplingChannelNumSpinner.selectedItemPosition
        )
        prefsEditor.putBoolean(
            KEY_SAMPLING_BLUETOOTH_SCO_ENABLE,
            binding.samplingBluetoothScoSwitch.isChecked
        )
        prefsEditor.putBoolean(
            KEY_SAMPLING_AUDIO_PTS_OPTIMIZE_ENABLE,
            binding.samplingAudioPtsOptimizeSwitch.isChecked
        )
        prefsEditor.putBoolean(KEY_SAMPLING_AEC_ENABLE, binding.samplingAecSwitch.isChecked)
        prefsEditor.putBoolean(KEY_SAMPLING_NSE_ENABLE, binding.samplingNseSwitch.isChecked)

        // PLWatermarkSetting
        prefsEditor.putFloat(
            KEY_WATERMARK_HEIGHT,
            transProgressToWatermarkSize(binding.watermarkHeightSeekbar.progress)
        )
        prefsEditor.putFloat(
            KEY_WATERMARK_WIDTH,
            transProgressToWatermarkSize(binding.watermarkWidthSeekbar.progress)
        )
        prefsEditor.putInt(
            KEY_WATERMARK_ALPHA,
            transProgressToWatermarkAlpha(binding.watermarkAlphaSeekBar.progress)
        )
        var watermarkPositionX: Float = binding.watermarkPositionXEdittext.text.toString().toFloat()
        var watermarkPositionY: Float = binding.watermarkPositionYEdittext.text.toString().toFloat()
        if (watermarkPositionX > 1) {
            watermarkPositionX = 0f
        }
        if (watermarkPositionY > 1) {
            watermarkPositionY = 0f
        }
        prefsEditor.putFloat(KEY_WATERMARK_POSITION_X, watermarkPositionX)
        prefsEditor.putFloat(KEY_WATERMARK_POSITION_Y, watermarkPositionY)
        prefsEditor.putInt(
            KEY_WATERMARK_SETTING_TYPE_POS,
            binding.watermarkSpinner.selectedItemPosition
        )
        prefsEditor.apply()
    }
}